﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Description;
using System.Threading.Tasks;
using System.Data.Entity;
using Microsoft.AspNet.Identity;
using YlisChat.Models;
using YlisChat.DAO;

namespace YlisChat.Controllers
{
    [Authorize]
    public class ChannelController : BaseController
    {
        /// <summary>
        /// Returns all public channels available
        /// GET api/channel
        /// </summary>
        /// <returns>all public channels</returns>
        [ResponseType(typeof(List<ChannelModel>))]
        public async Task<IHttpActionResult> Get()
        {
            List<ChannelModel> channels = await (from cha in db.Channels
                                                 where cha.Private == false
                                                 select cha).ToListAsync();
            return this.Ok(channels);
        }

        /// <summary>
        /// Search for public channels
        /// GET api/channel/name
        /// </summary>
        /// <param name="name">The channel to search</param>
        /// <returns>All public channels whose name match</returns>
        [ResponseType(typeof(List<ChannelModel>))]
        public async Task<IHttpActionResult> Get(string id)
        {
            List<ChannelModel> channels = await (from cha in db.Channels
                                                 where cha.Private == false
                                                 where cha.HashTag.Contains(id)
                                                 select cha).ToListAsync();
            return this.Ok(channels);
        }

        /// <summary>
        /// Create a channel
        /// POST api/channel
        /// </summary>
        /// <param name="value"></param>
        public async Task<IHttpActionResult> Post(ChannelModel channel)
        {
            if (channel == null)
                return this.BadRequest("No request data");

            if (!this.ValidateChannel(channel))
                return this.BadRequest("Invalid data");

            ChannelModel existing = await (from cha in db.Channels
                                           where channel.HashTag == cha.HashTag
                                           select cha).FirstOrDefaultAsync();
            if (existing != default(ChannelModel))
                return this.BadRequest("Channel already exists");

            ApplicationUser user = UserManager.FindById(User.Identity.GetUserId());
            UserList luser = new UserList()
            {
                UserId = user.Id,
                HashTag = channel.HashTag,
                AdminState = AdminLevel.ADMIN
            };
            db.Channels.Add(channel);
            db.UserList.Add(luser);
            await db.SaveChangesAsync();

            // Send the join message
            MessageDAO mdao = new MessageDAO(db);
            mdao.SendSystemMessage(String.Format("@{0} created {1}", luser.UserId, luser.HashTag), luser.HashTag, luser.UserId);

            return this.Ok(1);
        }

        /// <summary>
        /// Update a channel status
        /// PUT api/channel
        /// </summary>
        /// <param name="channel">The new channel data</param>
        public async Task<IHttpActionResult> Put(ChannelModel channel)
        {
            if (channel == null)
                return this.BadRequest("No request data");

            if (!this.ValidateChannel(channel))
                return this.BadRequest("Invalid data");

            ChannelModel existing = await (from cha in db.Channels
                                           where channel.HashTag == cha.HashTag
                                           select cha).FirstOrDefaultAsync();
            if (existing == default(ChannelModel))
                return this.BadRequest("Channel not found");

            // Check that user is admin on a channel
            ApplicationUser user = UserManager.FindById(User.Identity.GetUserId());
            UserList luser = await (from usrl in db.UserList
                                    where usrl.HashTag == existing.HashTag
                                    where usrl.UserId == user.Id
                                    where usrl.AdminState == AdminLevel.ADMIN
                                    select usrl).FirstOrDefaultAsync();
            if (luser == default(UserList))
                return this.Unauthorized();

            existing.Private = channel.Private;
            existing.Topic = channel.Topic;
            await db.SaveChangesAsync();
            return this.Ok();
        }

        // DELETE api/channel/name
        public IHttpActionResult Delete(string name)
        {
            return this.NotFound();
        }

        private bool ValidateChannel(ChannelModel channel)
        {
            if (String.IsNullOrWhiteSpace(channel.HashTag))
                return false;

            if (channel.HashTag[0] == '#' || channel.HashTag[0] == '@')
                return true;

            return false;
        }
    }
}
